package cool.webstudy.admin.service.impl;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import cool.webstudy.admin.constant.enums.DelFlagEnum;
import cool.webstudy.admin.constant.enums.EnabledStatusFlagEnum;
import cool.webstudy.admin.constant.enums.rescode.DictTypeResCodeEnum;
import cool.webstudy.admin.exception.BusinessException;
import cool.webstudy.admin.mapper.dictType.DictTypeMapper;
import cool.webstudy.admin.model.dto.dict.type.CreateDictTypeDTO;
import cool.webstudy.admin.model.dto.dict.type.PaginationQueryDictTypeListDTO;
import cool.webstudy.admin.model.dto.dict.type.UpdateDictTypeDTO;
import cool.webstudy.admin.model.dto.user.UserDetailInfoDTO;
import cool.webstudy.admin.model.po.dict.DictTypePO;
import cool.webstudy.admin.model.vo.dict.type.PaginationQueryDictTypeListVO;
import cool.webstudy.admin.model.vo.dict.type.QueryEnabledDictTypeRoughInfoVO;
import cool.webstudy.admin.service.DictTypeService;
import cool.webstudy.admin.utils.UserDetailUtil;
import cool.webstudy.common.constant.CommonConstant;
import cool.webstudy.common.utils.UUIDUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 作者：陈先生
 * 日期：2024/8/3
 * 描述:
 */
@Service
public class DictTypeServiceImpl implements DictTypeService {
    @Autowired
    private DictTypeMapper dictTypeMapper;

    /**
     * @param dto 创建字典类型接口请求参数模型
     * @return 是否成功的标志
     * @description: 创建字典类型
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean createDictType(CreateDictTypeDTO dto) {
        UserDetailInfoDTO userDetailInfo = UserDetailUtil.getUserDetailInfo();
        DictTypePO dictTypePO = new DictTypePO();
        dictTypePO.setParentUnCode(StringUtils.isBlank(dto.getParentUnCode()) ? CommonConstant.TREE_ROOT_NODE_UNCODE : dto.getParentUnCode());
        dictTypePO.setType(dto.getType());
        dictTypePO.setName(dto.getName());
        dictTypePO.setRemark(dto.getRemark());
        dictTypePO.setCreateBy(userDetailInfo.getAccount());
        dictTypePO.setCreateTime(new Date());
        dictTypePO.setUpdateBy(userDetailInfo.getAccount());
        dictTypePO.setUpdateTime(new Date());
        dictTypePO.setStatusFlag(EnabledStatusFlagEnum.ENABLED);
        dictTypePO.setUnCode(UUIDUtil.getUUID());
        dictTypePO.setDelFlag(DelFlagEnum.NOT_DEL_FLAG.getFlag());
        try {
            dictTypeMapper.insert(dictTypePO);
        } catch (Exception e) {
            throw new BusinessException(DictTypeResCodeEnum.RC_ERROR_CREATE);
        }

        return true;
    }

    /**
     * @param unCode 要删除的字典类型id
     * @return 是否成功的标志
     * @description: 创建字典类型
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteDictType(String unCode) {
        UserDetailInfoDTO userDetailInfo = UserDetailUtil.getUserDetailInfo();
        LambdaUpdateWrapper<DictTypePO> updateDictTypeWrapper = new LambdaUpdateWrapper<DictTypePO>();
        updateDictTypeWrapper.eq(DictTypePO::getUnCode, unCode)
                .set(DictTypePO::getDelFlag, DelFlagEnum.DEL_FLAG.getFlag())
                .set(DictTypePO::getUpdateBy, userDetailInfo.getAccount())
                .set(DictTypePO::getUpdateTime, new Date());
        try {
            dictTypeMapper.update(null, updateDictTypeWrapper);
        } catch (BusinessException e) {
            throw new BusinessException(DictTypeResCodeEnum.RC_ERROR_DELETE);
        }
        return true;
    }

    /**
     * @param dto 更新字典类型接口请求参数模型
     * @return 是否成功的标志
     * @description: 更新字典类型
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateDictType(UpdateDictTypeDTO dto) {
        UserDetailInfoDTO userDetailInfo = UserDetailUtil.getUserDetailInfo();

        LambdaUpdateWrapper<DictTypePO> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(DictTypePO::getUnCode, dto.getUnCode())
                .set(DictTypePO::getParentUnCode, StringUtils.isBlank(dto.getParentUnCode()) ? CommonConstant.TREE_ROOT_NODE_UNCODE : dto.getParentUnCode())
                .set(DictTypePO::getName, dto.getName())
                .set(DictTypePO::getType, dto.getType())
                .set(DictTypePO::getRemark, dto.getRemark())
                .set(DictTypePO::getUpdateBy, userDetailInfo.getAccount())
                .set(DictTypePO::getUpdateTime, new Date());
        try {
            dictTypeMapper.update(null, updateWrapper);
        } catch (BusinessException e) {
            throw new BusinessException(DictTypeResCodeEnum.RC_ERROR_UPDATE);
        }
        return true;
    }

    /**
     * @param dto 分页获取字典类型表接口请求信息模型
     * @return 是否成功的标志
     * @description: 分页查询字典类型
     */
    @Override
    public Page<PaginationQueryDictTypeListVO> paginationQueryDictTypeList(PaginationQueryDictTypeListDTO dto) {
        Page<PaginationQueryDictTypeListVO> paginationQueryDictTypeListVOPage = new Page<>();
        Page<DictTypePO> page = new Page<>(dto.getCurrent(), dto.getPageSize());
        LambdaQueryWrapper<DictTypePO> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper.like(StringUtils.isNotBlank(dto.getContext()), DictTypePO::getName, dto.getContext())
                .or().like(StringUtils.isNotBlank(dto.getContext()), DictTypePO::getType, dto.getContext())
                .eq(StringUtils.isNotBlank(dto.getName()), DictTypePO::getName, dto.getName())
                .eq(StringUtils.isNotBlank(dto.getType()), DictTypePO::getType, dto.getType())
                .eq(StringUtils.isNotBlank(dto.getStatusFlag().getFlag()), DictTypePO::getStatusFlag, dto.getStatusFlag());
        Page<DictTypePO> dictTypePOPage = dictTypeMapper.selectPage(page, queryWrapper);
        if (Objects.isNull(dictTypePOPage)) {
            return paginationQueryDictTypeListVOPage;
        }
        List<PaginationQueryDictTypeListVO> paginationQueryDictTypeListVOList = new ArrayList<>();
        dictTypePOPage.getRecords().forEach(dictTypePO -> {
            PaginationQueryDictTypeListVO paginationQueryDictTypeListVO = new PaginationQueryDictTypeListVO();
            paginationQueryDictTypeListVO.setUnCode(dictTypePO.getUnCode());
            paginationQueryDictTypeListVO.setParentUnCode(dictTypePO.getParentUnCode());
            paginationQueryDictTypeListVO.setName(dictTypePO.getName());
            paginationQueryDictTypeListVO.setType(dictTypePO.getType());
            paginationQueryDictTypeListVO.setStatusFlag(dictTypePO.getStatusFlag());
            paginationQueryDictTypeListVO.setCreateBy(dictTypePO.getCreateBy());
            paginationQueryDictTypeListVO.setCreateTime(dictTypePO.getCreateTime());
            paginationQueryDictTypeListVO.setUpdateBy(dictTypePO.getUpdateBy());
            paginationQueryDictTypeListVO.setUpdateTime(dictTypePO.getUpdateTime());
            paginationQueryDictTypeListVOList.add(paginationQueryDictTypeListVO);
        });
        paginationQueryDictTypeListVOPage.setRecords(paginationQueryDictTypeListVOList);
        paginationQueryDictTypeListVOPage.setCurrent(dictTypePOPage.getCurrent());
        paginationQueryDictTypeListVOPage.setPages(dictTypePOPage.getPages());
        paginationQueryDictTypeListVOPage.setSize(dictTypePOPage.getSize());
        paginationQueryDictTypeListVOPage.setTotal(dictTypePOPage.getTotal());
        return paginationQueryDictTypeListVOPage;
    }

    @Override
    public List<Tree<String>> queryDictTypeTree() {
        LambdaQueryWrapper<DictTypePO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(DictTypePO::getUnCode, DictTypePO::getParentUnCode, DictTypePO::getName, DictTypePO::getType, DictTypePO::getStatusFlag, DictTypePO::getRemark);
        List<DictTypePO> dictTypePOList = dictTypeMapper.selectList(queryWrapper);
        if (Objects.isNull(dictTypePOList)) {
            return new ArrayList<>();
        }
        //将信息转化为树形结构
        //配置
        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        // 自定义属性名 都要默认值的
        treeNodeConfig.setIdKey(CommonConstant.TREE_NODE_UNCODE_KEY);
        treeNodeConfig.setParentIdKey(CommonConstant.TREE_NODE_PARENT_UNCODE_KEY);
        // 最大递归深度
        treeNodeConfig.setDeep(20);
        //转换器
        List<Tree<String>> treeNodes = TreeUtil.build(dictTypePOList, CommonConstant.TREE_ROOT_NODE_UNCODE, treeNodeConfig,
                (treeNode, tree) -> {
                    tree.setId(treeNode.getUnCode());
                    tree.setParentId(treeNode.getParentUnCode());
                    tree.setName(treeNode.getName());
                    // 扩展属性 ...
                    tree.putExtra("type", treeNode.getType());
                    tree.putExtra("statusFlag", treeNode.getStatusFlag());
                    tree.putExtra("remark", treeNode.getRemark());
                });
        return treeNodes;
    }

    /**
     * @return Map<String>
     * @description: 获取字典类型基本信息map，信息包含业务主键和字典类型名称的一一对应关系
     */
    @Override
    public Map<String, String> queryDictTypeRoughInfoMap() {
        LambdaQueryWrapper<DictTypePO> queryWrapper = new LambdaQueryWrapper<>();
        List<DictTypePO> dictTypePOList = dictTypeMapper.selectList(queryWrapper);
        if (Objects.isNull(dictTypePOList)) {
            return null;
        }
        Map<String, String> dictTypeRoughInfoMap = new HashMap<>();
        dictTypePOList.forEach(dictTypePO -> {
            dictTypeRoughInfoMap.put(dictTypePO.getUnCode(), dictTypePO.getName());
        });
        return dictTypeRoughInfoMap;
    }

    /**
     * @return List<QueryEnabledDictTypeRoughInfoVO> 获取启用的字典类型基本信息列表接口响应参数模型
     * @description: 获取启用的字典类型基本信息列表接口
     */
    @Override
    public List<QueryEnabledDictTypeRoughInfoVO> queryEnabledDictTypeRoughInfoList() {
        List<QueryEnabledDictTypeRoughInfoVO> queryEnabledDictTypeRoughInfoVOList = new ArrayList<>();
        LambdaQueryWrapper<DictTypePO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DictTypePO::getStatusFlag, EnabledStatusFlagEnum.ENABLED)
                .select(DictTypePO::getUnCode, DictTypePO::getName);
        List<DictTypePO> dictTypePOList = dictTypeMapper.selectList(queryWrapper);
        if (Objects.isNull(dictTypePOList)) {
            return queryEnabledDictTypeRoughInfoVOList;
        }
        dictTypePOList.forEach(dictTypePO -> {
            QueryEnabledDictTypeRoughInfoVO queryEnabledDictTypeRoughInfoVO = new QueryEnabledDictTypeRoughInfoVO();
            queryEnabledDictTypeRoughInfoVO.setUnCode(dictTypePO.getUnCode());
            queryEnabledDictTypeRoughInfoVO.setName(dictTypePO.getName());
            queryEnabledDictTypeRoughInfoVOList.add(queryEnabledDictTypeRoughInfoVO);
        });
        return queryEnabledDictTypeRoughInfoVOList;
    }

    /**
     * @param dictType 字典类型
     * @return String 字典类型业务主键
     * @description: 根据字典类型获取字典类型业务主键
     */
    @Override
    public String queryDictTypeUnCodeByDictType(String dictType) {
        LambdaQueryWrapper<DictTypePO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DictTypePO::getType, dictType)
                .select(DictTypePO::getUnCode);
        DictTypePO dictTypePO = dictTypeMapper.selectOne(queryWrapper);
        if (Objects.isNull(dictTypePO)) {
            return null;
        }
        return dictTypePO.getUnCode();
    }

}
